package cn.edu.lingnan.service.impl;

 import cn.edu.lingnan.mapper.LoginMapper;
 import cn.edu.lingnan.mapper.UserMapper;
 import cn.edu.lingnan.service.LoginService;

 import cn.edu.lingnan.user.dtos.LoginDto;
 import cn.edu.lingnan.user.dtos.RegisterDto;
 import cn.edu.lingnan.user.dtos.Result;
 import cn.edu.lingnan.user.pojos.Menu;
 import cn.edu.lingnan.user.pojos.User;
 import cn.edu.lingnan.user.vos.MenuVO;
 import cn.edu.lingnan.user.vos.Meta;
 import cn.edu.lingnan.user.vos.UserInfoVo;
 import cn.edu.lingnan.user.vos.UserRoutesVO;
 import cn.edu.lingnan.utils.JwtUtils;
 import cn.edu.lingnan.utils.MD5;
 import cn.edu.lingnan.utils.RegexUtils;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.RandomUtil;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
// import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;

 import java.util.*;
 import java.util.stream.Collectors;

@Service
@Slf4j
public class LoginServiceImpl  implements LoginService {
    @Autowired
    private LoginMapper loginMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserMapper userMapper;
    @Override
    public UserInfoVo login(LoginDto loginDto) {
        //去除用户名和密码前后的空格
        loginDto.setUserPassword(loginDto.getUserPassword().trim());
        loginDto.setUserName(loginDto.getUserName().trim());
        // 查询用户信息
        UserInfoVo userInfoVo = loginMapper.login(loginDto);

        if (userInfoVo == null) {
           return null;
        }

        log.info("登录成功，用户：{}，", userInfoVo);
        // 验证密码
        String salt=userInfoVo.getSalt();
        String password=loginDto.getUserPassword();
        System.out.println("密码："+password);
//        盐
        System.out.println("盐"+salt);
         log.info("密码：{}",MD5.md5Encrypt(password+salt));

        if(!userInfoVo.getUserPassword().equals(MD5.md5Encrypt(password+salt))){
             return null;
        }

        // 准备 JWT
        String jwt = JwtUtils.generateJwt(Map.of(
                "userId", userInfoVo.getUserId(),
                "userName", userInfoVo.getUserName()
        ));

        // 设置 Token 到 UserInfoVo
        userInfoVo.setToken(jwt);

        return userInfoVo;
    }



@Override
public List<MenuVO> getMenusByUserId(Integer userId) {
    // 1. 查询用户的菜单列表
    List<Menu> menus = loginMapper.findMenusByUserId(userId);

    // 2. 构建菜单树
    List<Menu> menuTree = buildMenuTree(menus, 0);

    // 3. 转换为 MenuVO 列表
    List<MenuVO> menuVOTree = menuTree.stream()
            .map(this::convertToMenuVO)
            .sorted(Comparator.comparing(MenuVO::getPath)) // 根据 path 排序
            .collect(Collectors.toList());
    return menuVOTree;
}

    @Override
    public List<String> findPermissionsByUserId(Integer userId) {
        return loginMapper.findPermissionsByUserId(userId);
    }

    /**
     * 注册
     * @param registerDto
     * @param request
     * @return
     */
    @Override
    @Transactional
    public Result register(RegisterDto registerDto, HttpServletRequest request) {
        if(!RegexUtils.isValidEmail(registerDto.getEmail())){
             return Result.error("邮箱格式不正确");
        }
        //检查邮箱验证码
        String key="register:code:"+registerDto.getEmail();
        String redisCode = stringRedisTemplate.opsForValue().get(key);
        if(!registerDto.getCode().equals(redisCode)){
            return Result.error("验证码错误");
        }
        //检查用户名是否重复
        UserInfoVo userInfoVo= userMapper.getUserByUserName(registerDto.getUserName());
        if(userInfoVo!=null){
            return Result.error("该用户已存在");
        }
        //设置盐
        String salt = UUID.randomUUID().toString().replace("-", "").substring(0, 6);
        registerDto.setSalt(salt);
        User user = new User();
        BeanUtil.copyProperties(registerDto,user);
        user.setUserPassword(MD5.md5Encrypt(registerDto.getUserPassword().trim() + salt));
        user.setNickName("user_"+RandomUtil.randomString(10));
        user.setAvatar("https://ongoingife.oss-cn-beijing.aliyuncs.com/user_avatar/default.png");
        user.setRemark("学生注册");
        user.setType(2);
        int count = userMapper.insert(user);

        // 插入用户角色关系表
        if(count>0){
          userMapper.insertUserRole(user.getUserId(),3);
        }
        //删除验证码
        stringRedisTemplate.delete(key);

        return  Result.success();
    }


    /**
     * 构建菜单树
     * @param menus 所有菜单
     * @param parentId 父级ID
     * @return 菜单树
     */
    private List<Menu> buildMenuTree(List<Menu> menus, Integer parentId) {
        List<Menu> tree = new ArrayList<>();
        for (Menu menu : menus) {
            if (Objects.equals(menu.getParentId(), parentId)) {
                List<Menu> children = buildMenuTree(menus, menu.getMenuId());
                menu.setChildren(children);
                tree.add(menu);
            }
        }
        return tree;
    }

    /**
     * 将 Menu 实体转换为 MenuVO
     * @param menu Menu 实体
     * @return MenuVO
     */
    private MenuVO convertToMenuVO(Menu menu) {
        MenuVO vo = new MenuVO();
        vo.setPath(menu.getPath());
        vo.setName(menu.getMenuName());
        vo.setComponent(menu.getComponent());

        // 设置 meta 信息
        Meta meta = new Meta();
        meta.setTitle(menu.getMenuName());
        meta.setIcon(menu.getIcon());
        vo.setMeta(meta);

        // 设置子菜单
        if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {
            List<MenuVO> children = menu.getChildren().stream()
                    .map(this::convertToMenuVO)
                    .sorted(Comparator.comparing(MenuVO::getPath)) // 根据 path 排序
                    .collect(Collectors.toList());
            vo.setChildren(children);
        }
        return vo;
    }
}
